﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Chromium;
using Chromium.Remote;
using Chromium.WebBrowser;
using Kugar.Core.ExtMethod;
using Newtonsoft.Json.Linq;

namespace Kugar.UI.RazorUI.Helpers
{
    internal class CefValueHelper
    {
        public static object ToPrimitive(CfrV8Value value,BrowserCore browser)
        {
            if (value.IsBool)
            {
                return value.BoolValue;
            }
            else if (value.IsDate)
            {
                var dt = value.DateValue;

                return new DateTime(dt.Year, dt.Month, dt.DayOfMonth, dt.Hour, dt.Minute, dt.Second, dt.Millisecond, DateTimeKind.Local);
            }
            else if (value.IsDouble)
            {
                return value.DoubleValue;
            }
            else if (value.IsInt)
            {
                return value.IntValue;
            }
            else if (value.IsString)
            {
                return value.StringValue;
            }
            else if (value.IsUint)
            {
                return value.UintValue;
            }
            else if (value.IsNull || value.IsUndefined)
            {
                return null;
            }
            else if (value.IsArray)
            {
                var list = new object[value.ArrayLength];

                for (int i = 0; i < value.ArrayLength; i++)
                {
                    list[i] = ToPrimitive(value.GetValue(i),browser);
                }

                return list;
            }
            else if (value.IsObject)
            {
                return new JsonObjectProxy(value.RemotePtr.ToStringEx(), browser);

                //var keys = new List<string>();

                //if (value.GetKeys(keys))
                //{
                //    dynamic obj = new ExpandoObject();

                //    foreach (var key in keys)
                //    {
                //        obj.key = toPrimite(value.GetValue(key));
                //    }

                //    return new JsonObjectProxy(value.RemotePtr.ToStringEx(),browser);
                //}
                //else
                //{
                //    return new ExpandoObject();
                //}
            }
            else
            {
                throw new ArgumentException();
            }

        }

        public static string ToCfrJsParameter(object value)
        {
            if (value is string str)
            {
                return $"'{str}'";
            }
            else if(value is DateTime dt)
            {
                return $"Date.parse({dt.ToJavaScriptMilliseconds()})";
            }
            else if (value is bool b)
            {
                return value.ToString().ToLower();
            }

            return value.ToStringEx();
        }

        public static CfrV8Value ToCfrV8Value(object value)
        {
            if (value is bool)
            {
                return CfrV8Value.CreateBool((bool)value);
            }
            else if (value is DateTime dt)
            {
                return CfrV8Value.CreateDate(new CfrTime()
                {
                    Year = dt.Year, Month = dt.Month, DayOfMonth = dt.Day, Hour = dt.Hour, Minute = dt.Minute,
                    Second = dt.Second, Millisecond = dt.Millisecond
                });

            }
            else if (value is double db )
            {
                return CfrV8Value.CreateDouble(db);
            }
            else if (value is decimal dec)
            {
                return CfrV8Value.CreateDouble((double)dec);
            }
            else if (value is float f)
            {
                return CfrV8Value.CreateDouble((double)f);
            }
            else if (value is int tmpInt)
            {
                return CfrV8Value.CreateInt(tmpInt);
            }
            else if (value is short tmpShort)
            {
                return CfrV8Value.CreateInt(tmpShort);
            }
            else if (value is ushort tmpUShort)
            {
                return CfrV8Value.CreateInt(tmpUShort);
            }
            else if (value is uint tmpUInt)
            {
                return CfrV8Value.CreateUint(tmpUInt);
            }
            else if (value is string str)
            {
                return CfrV8Value.CreateString(str);
            }
            else if (value==null)
            {
                return CfrV8Value.CreateNull();
            }
            else if(value is JToken json)
            {
                return ToCfrV8Value(json);
            }
            else if (value is Array array)
            {
                var arr = CfrV8Value.CreateArray(array.Length);

                for (int i = 0; i < array.Length; i++)
                {
                    arr.SetValue(i, ToCfrV8Value(array.GetValue(i)));
                }

                return arr;
            }
            else
            {
                throw new ArgumentException("不支持该类型的转换");
            }

        }

        public static CfrV8Value ToCfrV8Value(JToken json)
        {

            CfrV8Value output = null;
            if (json.Type == JTokenType.Array)
            {
                var arrLength = json.Count();
                output = CfrV8Value.CreateArray(arrLength);
                for (var i = 0; i != arrLength; i++)
                    output.SetValue(i, ToCfrV8Value(json[i]));
            }
            else if (json.Type == JTokenType.Object)
            {
                var accessor = new CfrV8Accessor();

                output = CfrV8Value.CreateObject(accessor);

                var childrens = json.Children();

                foreach (dynamic child in childrens)
                {
                    output.SetValue(child.Name, ToCfrV8Value(child), CfxV8PropertyAttribute.None);
                }
            }
            else
            {
                if (json.Type == JTokenType.Property)
                {
                    var val = ((JProperty)json).Value;
                    var valueType = val.Type;

                    if (valueType == JTokenType.String)
                        output = CfrV8Value.CreateString(val.Value<string>());
                    else if (valueType == JTokenType.Boolean)
                        output = CfrV8Value.CreateBool(val.Value<bool>());
                    else if (valueType == JTokenType.Integer)
                        output = CfrV8Value.CreateInt(val.Value<int>());
                    else if (valueType == JTokenType.Float)
                        output = CfrV8Value.CreateDouble(val.Value<double>());
                    else if (valueType == JTokenType.Null)
                        output = CfrV8Value.CreateNull();
                    else if (valueType == JTokenType.Date)
                        output = CfrV8Value.CreateDate(CfrTime.FromUniversalTime(val.Value<DateTime>()));
                }
            }

            return output;
        }
    }
}
